<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
<script src="../resources/common.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>

<script>
description("Tests importKey/deriveBits for PBKDF2");

jsTestIsAsync = true;

// -------------------------------------------------
// Successful password import and bits derivation
// -------------------------------------------------

var kPbkdf2SuccessVectors = [
  // Non-ascii password
  {
    password: [200, 201, 202, 203, 204, 205, 206, 207],
    salt: "salt",
    c: 20,
    dkLen: 16,
    hash: "SHA-1",
    derived_key: "a7950c143ec64e2b8d4bb1db8677188b"
  },

  // Empty salt
  {
    password: "pass\0word",
    salt: "",
    c: 20,
    dkLen: 16,
    hash: "SHA-1",
    derived_key: "7deaf8b4a801011c1cd27f36e3bfc962"
  },

  // SHA-256
  {
    password: "password",
    salt: "salt",
    c: 20,
    dkLen: 16,
    hash: "SHA-256",
    derived_key: "83eb100b6a3a975f0fe3ffcdc2419852"
  },

  // SHA-512
  {
    password: "password",
    salt: "salt",
    c: 20,
    dkLen: 16,
    hash: "SHA-512",
    derived_key: "e4dfce3830983830c50c351a0b0f79e1"
  },

  // Empty password.
  {
    password: [],
    salt: "salt",
    c: 20,
    dkLen: 16,
    hash: "SHA-384",
    derived_key: "750261780a187897a9978371599db5d1"
  },
];

function runPbkdf2SuccessTestCase(testCase)
{
    var algorithm = {name: 'PBKDF2'};

    var key = null;
    var password = null;
    if (typeof testCase.password === 'string')
        password = asciiToUint8Array(testCase.password);
    else if (Array.isArray(testCase.password))
        password = new Uint8Array(testCase.password);

    var usages = ['deriveBits', 'deriveKey'];
    var extractable = false;

    var params = {
        name: 'PBKDF2',
        salt: asciiToUint8Array(testCase.salt),
        iterations: testCase.c,
        hash: {name: testCase.hash}
    };
    // (1) Import the password
    return crypto.subtle.importKey('raw', password, algorithm, extractable, usages).then(function(result) {
        key = result;
        // shouldBe() can only resolve variables in global context.
        tmpKey = key;
        shouldEvaluateAs("tmpKey.type", "secret");
        shouldEvaluateAs("tmpKey.extractable", false);
        shouldEvaluateAs("tmpKey.algorithm.name", "PBKDF2");
        shouldEvaluateAs("tmpKey.usages.join(',')", "deriveKey,deriveBits");

        // (2) Derive bits
        return crypto.subtle.deriveBits(params, key, testCase.dkLen*8);
    }).then(function(result) {
        bytesShouldMatchHexString("deriveBits", testCase.derived_key, result);
    });
}

var lastPromise = Promise.resolve(null);

kPbkdf2SuccessVectors.forEach(function(test) {
    lastPromise = lastPromise.then(runPbkdf2SuccessTestCase.bind(null, test));
});

lastPromise.then(finishJSTest, failAndFinishJSTest);

</script>

</body>
</html>
